//
//  walterFlowLayout.m
//  CollectionFlow
//
//  Created by bj_szd on 2025/5/6.
//

#import "WalterFlowLayout.h"

@interface WalterFlowLayout ()

@property (nonatomic, strong) NSMutableArray *attributeArray;
// 整个 collectionView 的 contenView 的高度
@property (nonatomic,assign) CGFloat contentHeight;
// 间距
@property (nonatomic,assign) CGFloat cellMargin;

@property (nonatomic,assign) CGFloat itemWidth;

@end

@implementation WalterFlowLayout

- (instancetype)init {
    if (self = [super init]) {
        _attributeArray = [NSMutableArray array];
        _numberOfColumns = 2;
        _cellMargin = 5.0;
        _contentHeight = 0.0f;
    }
    return self;
}
// 计算 item 的宽度
-(CGFloat)itemWidth {
    // 所有边距的和
    // 两列时有三个边距, 三列时有四个边距......
    CGFloat allMargin = (_numberOfColumns + 1) * _cellMargin;
    // 除去边界之后的总宽度
    CGFloat allWidth = CGRectGetWidth(self.collectionView.bounds) - allMargin;
    // 列的宽度，也就是 itemWidth
    return allWidth / _numberOfColumns;
}
// UICollectionView 在进行 UI 布局前，会通过这个类的对象获取相关的布局信息，就是 UICollectionViewLayoutAttributes
// 该类将这些布局信息全部存放在了一个数组中，通过 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect 返回该数组
 
// 重写该方法：计算 item 布局
- (void)prepareLayout {
    // 定义变量记录高度最小的列：初始为第 0 列高度最小
    NSInteger shortestColumn = 0;
    // 存储每一列的总高度
    NSMutableArray *columnHeightArray = [NSMutableArray array];
    // 列的初始高度：边距高度
    for (int i = 0; i < _numberOfColumns; ++i) {
        [columnHeightArray addObject:@(_cellMargin)];
    }
    // 遍历 collectionView 中第 0 区中的所有 item
    for (int i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        // 获取布局属性对象，就是每个 item 的布局属性
        UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
        // 将布局属性放入数组中
        [_attributeArray addObject:layoutAttributes];
        // 开始设置每个 item  的位置(x, y, width, height)
        // 比如一共两列，现在要放一张图片上去，需要放到高度最小的那一列
        // 假设第 0 列最短，那么 item 的 x 坐标就是从一个边距宽度那里开始
        
        // 橫坐标
        CGFloat x = (self.itemWidth + _cellMargin) * shortestColumn + _cellMargin;
        // 纵坐标就是 总高度数组 中最小列对应的高度
        CGFloat y = [columnHeightArray[shortestColumn] floatValue];
        // 宽度
        CGFloat width = self.itemWidth;
        
        // 这里给自定义的类声明了一个协议
        // 通过协议得到图片的高度，调用时机就是需要 item 高度的时候
        // 将 Item 的宽度传给代理（ViewController），VC 计算好高度后将高度返回给自定义类
        CGFloat height = [self.delegate collectionView:self.collectionView layout:self width:self.itemWidth heightForItemAtIndexPath:indexPath];
        // item 的位置信息
        layoutAttributes.frame = CGRectMake(x, y, width, height);
        
        // 现在开始更新总高度数组
        columnHeightArray[shortestColumn] = @([columnHeightArray[shortestColumn] floatValue] + height + _cellMargin);
        // 整个内容的高度，通过比较得到较大值作为整个内容的高度
        self.contentHeight = MAX(self.contentHeight, [columnHeightArray[shortestColumn] floatValue]);
        // 刚才放了一个 item 上去，现在开始找出高度最小的那个列
        for (int i = 0; i < _numberOfColumns; ++i) {
            // 当前列的高度：刚才添加 item 的那一列
            CGFloat currentHeight = [columnHeightArray[shortestColumn] floatValue];
            // 取出第 i 列中存放列高度
            CGFloat height = [columnHeightArray[i] floatValue];
            if (currentHeight > height) {
                // 第 i 列高度最低时赋值给高度最小的列
                shortestColumn = i;
            }
        }
    }
}
// 返回的是每个 item 对应的布局属性
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    return _attributeArray;
}
// 返回 CollectionView 的滚动范围
- (CGSize)collectionViewContentSize {
    return CGSizeMake(0, _contentHeight);
}

@end
